package com.cloud.gateway.exception;

import com.cloud.common.bean.ResultInfo;
import com.cloud.common.util.JsonUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.math.NumberUtils;
import org.springframework.boot.web.reactive.error.ErrorWebExceptionHandler;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Flux;
import reactor.core.publisher.Mono;

import java.nio.charset.StandardCharsets;

/**
 * 全局异常处理
 *
 * @author fengwenjin
 * @since 2021/7/14
 */
@Slf4j
@Configuration
@Order(Ordered.HIGHEST_PRECEDENCE)
public class GlobalExceptionHandler implements ErrorWebExceptionHandler {
    @Override
    public Mono<Void> handle(ServerWebExchange exchange, Throwable e) {
        String requestURI = exchange.getRequest().getURI().getPath();
        String errorMessage = "requestURI=" + requestURI + ", errorMsg >>> " + e.getMessage();
        if (exchange.getResponse().isCommitted()) {
            log.warn(errorMessage + ", response committed", e);
            return Mono.error(e);
        }
        // 错误码解析
        boolean isNotFound = false;
        ResultInfo resultInfo = ResultInfo.failure();
        String[] msgArr = e.getMessage().split(" ");
        if (msgArr.length > 0) {
            int statusCode = NumberUtils.toInt(msgArr[0], HttpStatus.EXPECTATION_FAILED.value());
            resultInfo.setCode(statusCode);
            if (statusCode == HttpStatus.NOT_FOUND.value() || statusCode == HttpStatus.SERVICE_UNAVAILABLE.value()) {
                resultInfo.setMessage("服务不存在");
                isNotFound = true;
            }
        }
        errorMessage = errorMessage + ", resultInfo >>> " + resultInfo.toString();
        if (isNotFound) {
            log.warn(errorMessage, e);
        } else {
            log.error(errorMessage, e);
        }

        byte[] bytes = JsonUtils.toJSONString(resultInfo).getBytes(StandardCharsets.UTF_8);
        ServerHttpResponse response = exchange.getResponse();
        response.getHeaders().setContentType(MediaType.APPLICATION_JSON);
        return response.writeWith(Flux.just(response.bufferFactory().wrap(bytes)));
    }
}
